		TITLE	LIBASE - Copyright (c) SLR Systems 1994

		INCLUDE	MACROS
		INCLUDE	SEGMENTS


		PUBLIC	LIBASE_FLUSH


		.DATA

		EXTERNDEF	FIX2_LD_TYPE:BYTE

		EXTERNDEF	LIDATA_RELOCS_START:DWORD,LIBASE_TEMP_RECORD:DWORD,FIX2_LDATA_EOR:DWORD,LIDATA_RELOCS_NEXT:DWORD
		EXTERNDEF	FIX2_LDATA_PTR:DWORD,FIX2_LDATA_LOC:DWORD


		.CODE	PASS2_TEXT

		EXTERNDEF	OBJ_PHASE:PROC,EXE_RELOC_FLUSH:PROC,LIBASE_RELOC_INSTALL:PROC,_abort:proc
		EXTERNDEF	RELEASE_BLOCK:PROC,DO_PE_RELOC:PROC


LIBASE_VARS	STRUC

LIBASE_LEVEL_BP		DD	?
LIBASE_RSEGMENT_BP	DD	?
LIBASE_ROFFSET_BP	DD	?
LIBASE_RTYPE_BP		DD	?
LIBASE_OFFSET_BP	DD	?
LIBASE_PTR_BP		DD	?
REPEAT_MASK_BP		DD	?
REPEAT_SIZE_2_BP	DD	?

LIBASE_VARS	ENDS


FIX	MACRO	X

X	EQU	([EBP - SIZEOF LIBASE_VARS].(X&_BP))

	ENDM


FIX	LIBASE_LEVEL
FIX	LIBASE_RSEGMENT
FIX	LIBASE_ROFFSET
FIX	LIBASE_RTYPE
FIX	LIBASE_OFFSET
FIX	LIBASE_PTR
FIX	REPEAT_MASK
FIX	REPEAT_SIZE_2


LIBASE_FLUSH	PROC
		;
		;IF ANY RELOCS EXIST FOR THIS RECORD, FLUSH THEM PLEASE...
		;
		MOV	ECX,LIDATA_RELOCS_NEXT
		MOV	EAX,LIDATA_RELOCS_START

		TEST	ECX,ECX
		JZ	L9$

		CMP	EAX,ECX
		JZ	L8$
		PUSHM	EBP,EBX,EDI,ESI

		MOV	EBP,ESP
		ASSUME	EBP:PTR LIBASE_VARS
		SUB	ESP,SIZEOF LIBASE_VARS

		MOV	ESI,EAX
		MOV	AL,FIX2_LD_TYPE

		MOV	EDI,-1			;KEEP 32 BITS
		MOV	EBX,6			;UPDATE POINTER BY 4

		AND	AL,MASK BIT_32
		JNZ	L0$

		MOV	EDI,0FFFFH		;OOPS, JUST KEEP 16 BITS
		SUB	EBX,2			;UPDATE POINTER BY 2

L0$:
		MOV	REPEAT_MASK,EDI
		MOV	REPEAT_SIZE_2,EBX

		JMP	L1$

L8$:
if	fg_pe
		GETT	DL,OUTPUT_PE
		XOR	ECX,ECX

		OR	DL,DL
		JZ	L9$

		MOV	LIDATA_RELOCS_NEXT,ECX
		JMP	RELEASE_BLOCK

endif
L9$:
		RET

L1$:
		;
		;SET STUFF UP FOR CALLING LIBASE_PROC
		;
		MOV	EDI,FIX2_LDATA_PTR
		MOV	EBX,[ESI]

		ADD	ESI,4
if	fg_pe
		GETT	AL,OUTPUT_PE

		OR	AL,AL
		JZ	L2$

		AND	FIX2_LD_TYPE,NOT MASK BIT_LI	;SO DO_PE_RELOC WORKS...
		JMP	L3$
endif

L2$:
		MOV	EAX,[ESI]
		MOV	ECX,FIX2_LDATA_LOC

		SUB	EBX,ECX			;GET OFFSET FROM LIDATA REC
		MOV	LIBASE_ROFFSET,EAX	;TARGET OFFSET
		;
		;AX IS OFFSET IN SEGMENT
		;BX IS _RL_IMP_OFFSET
		;CL IS FIXUPP TYPE
		;CH IS FIXUPP FLAGS
		;DX IS _RL_IMP_MODULE
		;
		MOV	EAX,4[ESI]
		MOV	ECX,8[ESI]

		ADD	ESI,12
		MOV	LIBASE_RTYPE,EAX	;TYPE OF REFERENCE

		MOV	LIBASE_RSEGMENT,ECX	;TARGET SEGMENT
L3$:
		PUSH	ESI
		CALL	LIBASE_PROC

		POP	ESI
		MOV	EBX,LIDATA_RELOCS_NEXT


		CMP	LIDATA_RELOCS_NEXT,ESI
		JNZ	L1$

		MOV	EAX,LIDATA_RELOCS_START
		MOV	ESP,EBP

		MOV	LIDATA_RELOCS_NEXT,EAX

		POPM	ESI,EDI,EBX,EBP

		JMP	L8$

LIBASE_FLUSH	ENDP


LIBASE_PROC	PROC	NEAR
		;
		;EDI+EBX IS DESIRED LOCATION
		;
		ADD	EBX,EDI
		MOV	EDI,OFF LIBASE_TEMP_RECORD

		MOV	LIBASE_PTR,EBX
		XOR	EDX,EDX

		MOV	ESI,FIX2_LDATA_PTR
		MOV	LIBASE_LEVEL,EDX

		RESS	FOUND_BASE,DL
		MOV	LIBASE_OFFSET,EDX

		MOV	[EDI+4],EDX		;ZERO BYTES SO FAR
		INC	EDX

		MOV	[EDI],EDX		;REPEAT COUNT == 1
		ADD	EDI,8

		;FIRST WE BUILD TABLE DEFINING LIDATA RECORD VS ITEM FIXED UP

LIBASE_PROC_LOOP:
		CALL	LIBASE_LOOPER

		GETT	AL,FOUND_BASE
		MOV	ECX,FIX2_LDATA_EOR

		OR	AL,AL
		JNZ	SETUP_TABLE

		CMP	ECX,ESI
		JA	LIBASE_PROC_LOOP

		JNZ	ERRR

		RET

ERRR:
		CALL	OBJ_PHASE
		JMP	_abort

LIBASE_LOOPER:
		MOV	ECX,1		;BLOCK COUNT

		MOV	EBX,ECX		;REPEAT COUNT
		JMP	LIBASE

DO_MULT::
		;
		;BLOCK COUNT = 1, SO JUST MULTIPLY NEXT REPT TIMES LAST
		;
		MOV	EAX,REPEAT_SIZE_2
		MOV	EBX,[ESI]

		ADD	ESI,EAX
		MOV	EAX,REPEAT_MASK

		AND	EAX,EBX		;EBX IS REPEAT
		PUSH	EDX		;SAVE NEST LEVEL

		MUL	DPTR [EDI-8]

		SUB	EDI,8
		MOV	EBX,EAX


		MOV	ECX,[ESI-2]
		POP	EDX


		AND	ECX,0FFFFH

LIBASE_PROC	ENDP

					;EBX IS REPEAT, ECX IS BLOCK CNT, EDX IS LEVEL
LIBASE		PROC	NEAR
		;
		;ESI IS RECORD
		;
		XOR	EAX,EAX
		MOV	[EDI],EBX

		MOV	[EDI+4],EAX	;BYTES GENERATED THIS LEVEL
		ADD	EDI,8

		CMP	ECX,1
		JB	GENERATE

		JZ	DO_MULT

BLOCK_LOOP:
		INC	EDX		;INCREMENT LEVEL
		MOV	EAX,REPEAT_SIZE_2

		MOV	EBX,[ESI]	;NEXT REPEAT FACTOR
		ADD	ESI,EAX

		MOV	EAX,REPEAT_MASK
		PUSH	ECX		;SAVE BLOCK COUNT

		AND	EBX,EAX		;EBX IS REPEAT
		MOV	ECX,[ESI-2]	;BLOCK COUNT

		AND	ECX,0FFFFH
		CALL	LIBASE

		POP	ECX		;BLOCK COUNT
		DEC	EDX

		DEC	ECX
		JNZ	BLOCK_LOOP	;DO LOOP AGAIN

GEN_RET:
		;
		;MULTIPLY BYTES GENERATED BY REPEAT COUNT, STORE IN PREVIOUS
		;BYTES GENERATED...
		;
		PUSH	EDX		;SAVE CURRENT LEVEL
		MOV	EAX,[EDI-8]

		MOV	ECX,[EDI-4]
		SUB	EDI,8

		MUL	ECX

		MOV	ECX,[EDI-4]
		POP	EDX

		ADD	ECX,EAX
		MOV	EBX,LIBASE_LEVEL

		MOV	[EDI-4],ECX
		;
		;DO WE UPDATE OTHER TABLE?
		;
		CMP	EBX,EDX

		MOV	ECX,[EDI-1024-4]
		JB	SKIP_UPDATE

		JE	SKIP_UPDATE_LEVEL

		DEC	EBX
SKIP_UPDATE_LEVEL:
		;
		;ON THE WAY DOWN, SO, UPDATE TABLE AT -1024[DI]
		;
		ADD	EAX,ECX

		MOV	LIBASE_LEVEL,EBX
		MOV	[EDI-1024-4],EAX
SKIP_UPDATE:
		RET			;BACK TO PREVIOUS LOOP?


GENERATE:
		;
		;GENERATE A FEW BYTES OF CODE...
		;
		;ECX IS 0
		;
		MOV	CL,[ESI]
		INC	ESI

		MOV	EAX,LIBASE_PTR
		MOV	[EDI-4],ECX	;STORE BYTES GENERATED

		CMP	EAX,ESI
		JAE	G1

		ADD	ESI,ECX
		JMP	GEN_RET

G1:
		;
		;AE, HMMM, ARE WE THERE YET?
		;
		ADD	ESI,ECX

		CMP	EAX,ESI
		JAE	GEN_RET
G2:
		;
		;FOUND IT !
		;
		SUB	EAX,ESI
		MOV	ECX,LIBASE_OFFSET

		ADD	EAX,ECX
		MOV	LIBASE_LEVEL,EDX
		;
		;COPY FROM LIBASE_TEMP_RECORD THRU EDI TO LIBASE_TEMP_RECORD+1024
		;
		MOV	LIBASE_OFFSET,EAX
		PUSH	ESI

		MOV	ESI,OFF LIBASE_TEMP_RECORD
		MOV	ECX,EDI

		MOV	EDI,OFF LIBASE_TEMP_RECORD+1024
		SUB	ECX,ESI

		SHR	ECX,3
G3:
		MOV	EBX,[ESI]
		MOV	EDX,[ESI+4]

		MOV	[ESI+1024],EBX
		MOV	[ESI+1024+4],EDX

		ADD	ESI,8
		ADD	EAX,EDX

		DEC	ECX
		JNZ	G3

		MOV	LIBASE_OFFSET,EAX
		MOV	[ESI],ECX	;REPEAT = ZERO AT END

		LEA	EDI,[ESI+1024]
		POP	ESI

		SETT	FOUND_BASE

		JMP	GEN_RET

LIBASE		ENDP


SETUP_TABLE	PROC	NEAR
		;
		;MAKE OPTIMIZATION PASS THROUGH TABLE
		;
		MOV	ESI,OFF LIBASE_TEMP_RECORD+8

		MOV	EDI,ESI
		;
		;MULTIPLY NEXT REPEAT TIMES BYTES GENERATED, COMPARE TO THIS
		;
ST_0:
		MOV	ECX,[ESI]
		ADD	ESI,4

		MOV	[EDI],ECX
		ADD	EDI,4

		CMP	ECX,1
		JB	ST_1

		JZ	ST_02
ST_01:
		MOV	EAX,[ESI]
		ADD	ESI,4

		MOV	[EDI],EAX
		ADD	EDI,4

		MUL	ECX
		;
		;SUBTRACT FROM PREVIOUS BYTES GENERATED
		;
		SUB	[EDI-12],EAX
		JMP	ST_0

ST_02:
		;
		;REPEAT FACTOR = 1, SKIP THIS GUY...
		;UNLESS DI = FIRST, AND NEXT = 0
		;
		CMP	EDI,OFF LIBASE_TEMP_RECORD+12
		JNZ	ST_03		;YES, SKIP IT...

		MOV	EAX,[ESI+4]

		TEST	EAX,EAX
		JZ	ST_01		;CANNOT SKIP
ST_03:
		ADD	ESI,4
		SUB	EDI,4

		JMP	ST_0

ST_1:
		;
		;OK, NOW EXPAND IT ALLOWING ROOM FOR COUNT_LEFT
		;
		SUB	EDI,4

		MOV	ECX,EDI
		MOV	ESI,EDI

		SUB	ECX,OFF LIBASE_TEMP_RECORD
		SUB	ESI,4

		SHR	ECX,1
		XOR	EAX,EAX

		ADD	EDI,ECX

		SHR	ECX,2
		SUB	EDI,8

		DEC	ECX

		MOV	[EDI+8],EAX
		JZ	ST_3
ST_2:
		MOV	EAX,[ESI]
		MOV	EDX,[ESI-4]

		MOV	[EDI],EAX
		MOV	[EDI-4],EDX

		SUB	ESI,8
		SUB	EDI,12

		DEC	ECX
		JNZ	ST_2
ST_3:
		;
		;WHEW!
		;NOW PROCESS TABLE
		;AFTER ALL THIS, CAN THERE BE ANY SPEED?????
		;
;		CALL	FINISH
;		RET

SETUP_TABLE	ENDP


FINISH		PROC	NEAR
		;
		;
		;
		MOV	ESI,OFF LIBASE_TEMP_RECORD+12
		MOV	EDX,LIBASE_OFFSET

		ADD	EDX,FIX2_LDATA_LOC

		MOV	EAX,[ESI]	;MOVE REPT_CNT TO REPT_CNT_LEFT

		MOV	[ESI+8],EAX
		ADD	ESI,12		;SKIP DELTA FACTOR TILL COMING BACK

LIBASE_OUTPUT_LOOP:

		MOV	EAX,[ESI]	;MOVE REPT_CNT TO REPT_CNT_LEFT
LIBASE_O_L:

		MOV	[ESI+8],EAX
		ADD	ESI,12		;SKIP DELTA FACTOR TILL COMING BACK

		TEST	EAX,EAX
		JZ	GENN_EXE_TAG

		MOV	EAX,[ESI]	;MOVE REPT_CNT TO REPT_CNT_LEFT
		CALL	LIBASE_O_L

		MOV	ECX,[ESI-8]
		MOV	EAX,[ESI-4]

		ADD	EDX,ECX		;ADD IN DELTA FACTOR
		DEC	EAX

		MOV	[ESI-4],EAX
		JNZ	LIBASE_OUTPUT_LOOP

		SUB	ESI,12
		RET

GENN_EXE_TAG:
		;
		;EDX IS ADDR, MAKE IT EAX
		;
		MOV	EAX,EDX
		SUB	ESI,12

GENN_EXE_TAG_LOOP:
		;
		;EAX IS OFFSET IN SEGMENT
		;
		PUSH	EAX
		;
if	fg_pe
		GETT	DL,OUTPUT_PE

		OR	DL,DL
		JZ	L5$

		CALL	DO_PE_RELOC

		JMP	L6$
endif

L5$:
		MOV	EBX,LIBASE_ROFFSET
		MOV	ECX,LIBASE_RTYPE

		MOV	EDX,LIBASE_RSEGMENT	;SEGMENT OR PARAGAPH
		CALL	LIBASE_RELOC_INSTALL
L6$:
		POP	EAX
		MOV	ECX,[ESI-8]

		MOV	EDX,[ESI-4]
		ADD	EAX,ECX

		DEC	EDX

		MOV	[ESI-4],EDX
		JNZ	GENN_EXE_TAG_LOOP

		MOV	EDX,EAX
		SUB	ESI,12

		RET

FINISH		ENDP


		END

